\documentclass[twoside,a4paper]{ctexart}
\usepackage{geometry}
\geometry{margin=1.5cm, vmargin={0pt,1cm}}
\setlength{\topmargin}{-1cm}
\setlength{\paperheight}{29.7cm}
\setlength{\textheight}{25.3cm}

% useful packages.
\usepackage{amsfonts}
\usepackage{amsmath}
\usepackage{amssymb}
\usepackage{amsthm}
\usepackage{enumerate}
\usepackage{graphicx}
\usepackage{multicol}
\usepackage{fancyhdr}
\usepackage{layout}
\usepackage[framemethod=tikz]{mdframed}
\usepackage{subfigure}

% some common command

\title{{\Huge{\textbf{Project 2}}}\\——Multigrid}
\author{邵柯欣}
\date{\today}


\newcommand{\dif}{\mathrm{d}}
\newcommand{\avg}[1]{\left\langle #1 \right\rangle}
\newcommand{\difFrac}[2]{\frac{\dif #1}{\dif #2}}
\newcommand{\pdfFrac}[2]{\frac{\partial #1}{\partial #2}}
\newcommand{\OFL}{\mathrm{OFL}}
\newcommand{\UFL}{\mathrm{UFL}}
\newcommand{\fl}{\mathrm{fl}}
\newcommand{\op}{\odot}
\newcommand{\Eabs}{E_{\mathrm{abs}}}
\newcommand{\Erel}{E_{\mathrm{rel}}}

\begin{document}

\maketitle

\pagestyle{fancy}
\fancyhead{}
\lhead{邵柯欣 (3200103310)}
\chead{Numerical PDE project 2}
\rhead{\today}

\section*{I. 文件介绍}
整个作业文件由三个子文件夹（src,doc,fig）构成，分别用来存放代码，报告，图片．所有文件通过Ｍakefile管理．只需在Ｍakefile所在目录下输入make，即可生成测试代码的可执行文件；在改目录下输入clean，就能删除make生成的文件，回到初始状态． 

\subsection*{I-a 求解使用方法介绍}
在头文件中引用"Solve.h"

定义求解器时，依次输入：N(分割细度), f(偏微分方程 u"), initv(初始猜测), TYPE(边界条件类型，＂Ｄ＂代表狄力克雷，＂Ｎ＂代表诺曼), ro(限制算子), io(插值算子), cycle(循环类型), D(维度1,2).

使用时根据维度调用子函数　solve1d(a, b, iter, epsilon)，$a,b$ 为边界条件，solve2d(d, iter, epsilon)，$d$ 为边界条件，$iter$ 为最大迭代次数，$epsilon$ 为精度，返回计算结果．

实例：
\begin{mdframed}[hidealllines=true,backgroundcolor=blue!20]
\begin{verbatim}
  #include "Solve.h"
  class F : public Function {
    ...
  };
  int main(){
    int N;
    F f;  
    vector<double> v0[N-1], v;
    Solver S(N,f,v0,"D","FullWeight","Linear","FMG");
    v = S.solve(U0[0],U0[N],40, 1e-8);
  }
\end{verbatim}
\end{mdframed}

\subsection*{I-b 求解器代码结构介绍} 
求解器核心是利用V-cycle求解$Au = f$问题．

这一次为了避免头文件里东西杂乱的问题，定义了多个头文件，每个头文件实现单一的功能类，用来实现功能和存储相应的变量．

\begin{mdframed}[hidealllines=true,backgroundcolor=blue!20]
  Grid.h 包含　Piont 结构, Gird 类
\end{mdframed}

\begin{itemize}
\item Point 结构用来模拟二维点的结构，有结构变量ｘｙ，表示两个坐标．
\item Grid 类用来存储一连串网格点的信息，Ｇ为所有网格点的坐标，IG为需要求解的网格点信息（例如狄力克雷边界条件下IG为Ｇ除去边界的点），Label负责给所有网格点标记，与Ｇ大小相等且一一对应，当点在圆内或圆上打上标签-1，当点在边界上时标记为０，否则将点添加到IG中标记为ｊ(j　为该点在IG中的坐标加１)
\end{itemize}

\begin{mdframed}[hidealllines=true,backgroundcolor=blue!20]
  MVoperator.h 包含 MatrixVectorOperator 类
\end{mdframed}

\begin{itemize}
\item MatrixVectorOperator类，主要有三个用途：
\item[1] $get\_*(N)$用于根据分割细度N生成对应的A,D,T,I;
\item[2] 定义矩阵和向量的常用运算函数. 如矩阵乘向量,向量相加,向量相减等;
\item[3] 根据输入的向量求范数(一范数，二范数，无穷范数).
\end{itemize}

\begin{mdframed}[hidealllines=true,backgroundcolor=blue!20]
  RI.h 包含 虚类 Function, RestrictionOperator, InterpolationOperator; 由虚类衍生的类 LinearInterpolationOperator, QuadraticInterpolationOperator, FullWeightingRestrictionOperator, InjectionRestrictionOperator
\end{mdframed}

\begin{itemize}
\item 虚类 Function, RestrictionOperator, InterpolationOperator 给出了函数，限制算子和插值算子的基本定义．
\item 由虚类衍生的类 LinearInterpolationOperator, QuadraticInterpolationOperator 给出了线性插值算子和二阶插值算子的具体定义
\item 由虚类衍生的类 FullWeightingRestrictionOperator, InjectionRestrictionOperator 给出了两种限制算子的具体定义
\end{itemize}

\begin{mdframed}[hidealllines=true,backgroundcolor=blue!20]
  Cycle.h
\end{mdframed}

\begin{itemize}
\item Cycle　类用来实现两种不同的循环（V-cycle, FMG）．
\end{itemize}

\begin{mdframed}[hidealllines=true,backgroundcolor=blue!20]
  Solve.h
\end{mdframed}

\begin{itemize}
\item Solver 类，输入变量为: Ｎ（分割细度）, f(偏微分方程 u''), initv(初始猜测), TYPE(边界条件类型，＂Ｄ＂代表狄力克雷，＂Ｎ＂代表诺曼), ro(限制算子), io(插值算子), cycle(循环类型).
\item[*] 子函数　solve1d(a, b, iter, epsilon); solve2d(d, iter, epsilon)　分别定义了一维和二维空间上的求解函数．
\item[*] ERROR 函数用来计算并输出误差的１范数，２范数，无穷范数．
\end{itemize}

\subsection*{I-c 对不合法输入的检测排除}
首先检测TYPE，当其输入值不为＂Ｄ＂或＂Ｎ＂时，输出错误，退出程序；
其次检测圆，当圆不能包含大于等于４个点或圆超出［０，１］＊［０，１］的区域时，输出错误，退出程序．

\section*{II. 测试代码介绍}
测试代码文件为"test.cpp".

对应的一维函数为$u(x) = e^{\sin(x)}$

对应的二维函数为$u(x,y) = e^{\sin(x)+y}$

测试代码中,对$N \in {32,64,128,256}$测试了两种组合的求解一维狄力克雷边界条件的求解器
\begin{itemize}
\item[1] FullWeight RestrictionOperator, Linear InterpolationOperator, FMG cycle
\item[2] FullWeight RestrictionOperator, Linear InterpolationOperator, V-cycle
\end{itemize}
在求解器的迭代过程中,对每一次迭代的残差,调用类$MatrixVectorOperator$中求范数的函数,输出其无穷范数.

\section*{III. 测试结果展示}
计算结果:
\begin{table}[h]
    \caption{FMG 残差无穷范数变化}\label{table1}
    \centering
    \begin{tabular}{|c|c|c|c|c|c|c|c|c|}
      \hline
      \textbf{N} & \multicolumn{2}{c|}{32} & \multicolumn{2}{c|}{64} & \multicolumn{2}{c|}{128} & \multicolumn{2}{c|}{256} \\
      \hline 
      \textbf{迭代次数} & \textbf{无穷范数} & \textbf{$\log$} & \textbf{无穷范数} & \textbf{$\log$} & \textbf{无穷范数} & \textbf{$\log$} & \textbf{无穷范数} & \textbf{$\log$}   \\
      \hline 
      0 & 2374    &  11.2    & 9337    &  13.1    & 16385   &  14.0    & 65537   &  16.0    \\
      1 & 140     &  7.13    & 554     &  9.11    & 972     &  9.92    & 3891    &  11.9    \\ 
      2 & 15.2    &  3.93    & 59.9    &  5.90    & 105     &  6.71    & 420     &  8.71    \\
      3 & 1.77    &  0.831   & 6.99    &  2.80    & 12.2    &  3.61    & 49.1    &  5.61    \\
      4 & 2.16e-1 & -2.20    & 8.52e-1 & -0.230   & 1.49    &  0.580   & 5.98    &  2.58    \\
      5 & 2.76e-2 & -5.17    & 1.08e-1 & -3.20    & 1.90e-1 & -2.39    & 7.62e-1 & -0.391 \\
      6 & 3.69e-3 & -8.08    & 1.45e-2 & -6.10    & 2.55e-2 & -5.29    & 1.02e-1 & -3.29    \\
      7 & 6.17e-4 & -10.6    & 2.47e-3 & -8.65    & 4.35e-3 & -7.84    & 1.74e-2 & -5.84    \\
      8 & 1.12e-4 & -13.1    & 4.57e-4 & -11.1    & 8.05e-4 & -10.2    & 3.21e-3 & -8.27    \\        
      \hline
    \end{tabular}
\end{table}

\begin{table}[h]
    \caption{V-cycle 残差无穷范数变化}\label{table1}
    \centering
    \begin{tabular}{|c|c|c|c|c|c|c|c|c|}
      \hline
      \textbf{N} & \multicolumn{2}{c|}{32} & \multicolumn{2}{c|}{64} & \multicolumn{2}{c|}{128} & \multicolumn{2}{c|}{256} \\
      \hline 
      \textbf{迭代次数} & \textbf{无穷范数} & \textbf{$\log$} & \textbf{无穷范数} & \textbf{$\log$} & \textbf{无穷范数} & \textbf{$\log$} & \textbf{无穷范数} & \textbf{$\log$}   \\
      \hline 
      0 & 2374    &  11.2  & 9337    &  13.1 & 16385   &  14.0  & 65537   &  16.0  \\
      1 & 158     &  7.31  & 622     &  9.28 & 1092    &  10.1  & 4369    &  12.1  \\
      2 & 26.7    &  4.74  & 105     &  6.72 & 185     &  7.53  & 741     &  9.53  \\
      3 & 4.2     &  2.09  & 16.8    &  4.07 & 29.6    &  4.89  & 118     &  6.89  \\
      4 & 6.79e-1 & -0.558 & 2.71    &  1.43 & 4.74    &  2.24  & 19.0    &  4.24  \\
      5 & 1.09e-1 & -3.19  & 4.37e-1 & -1.19 & 7.68e-1 & -0.379 & 3.07    &  1.62  \\
      6 & 1.76e-2 & -5.82  & 7.17e-2 & -3.80 & 1.25e-1 & -2.98  & 5.04e-1 & -0.987 \\
      7 & 2.89e-3 & -8.43  & 1.18e-2 & -6.39 & 2.08e-2 & -5.58  & 8.36e-2 & -3.57  \\
      8 & 4.77e-4 & -11.1  & 1.98e-3 & -8.97 & 3.49e-3 & -8.16  & 1.40e-2 & -6.15  \\     
      \hline
    \end{tabular}
\end{table}

\begin{figure}[htbp]
	\centering
	\subfigure[N = 32] {\includegraphics[width=.35\textwidth]{../fig/re32.png}}
	\subfigure[N = 64] {\includegraphics[width=.35\textwidth]{../fig/re64.png}}
	\subfigure[N = 128] {\includegraphics[width=.35\textwidth]{../fig/re128.png}}
        \subfigure[N = 256] {\includegraphics[width=.35\textwidth]{../fig/re256.png}}
	\caption{不同N下,V-cycle和FMG收敛速度比较}
	\label{fig_E1}
\end{figure}

误差收敛结论:

\section*{IV. 心得感悟}
我的代码实现了各种条件下一维的微分方程求解，对于二维的情况都没有实现．

这一次代码明显感觉比第一次代码的结构更加的清晰, 修改测试的时候都更加的方便. 第一次的时候我把所有实现代码都写在一起, 导致修改调试的时候需要一遍一遍的重新推演整个代码.

这次的代码在编写时及时加上注释, 让每个子函数功能更加分明清楚.

写程序之前我先对实现目标进行了取舍,虽然最后没有实现全部的要求, 但是实现了两种限制算子,两种插值算子,还有一维情况下的所有边界条件. 最后V-cycle和FMG迭代的收敛情况也很不错.

对比第九章的多重网格和第七章的直接求解, 可以明显感觉到多重网格的速度很快. 第一次项目作业时, 当$N = 128$, 求解时间需要几分钟; 而这一次项目作业, 即便$N = 256$, 求解器也可以很快的给出结果, 感受不到等待时间.
\end{document}
